
// ● 声明一个类接口，规定定义的类满足以下要求（name属性必传、age属性可选、sex属性只读，同时还拥有eat方法）（10分）
interface Info {
    name: string;
    age?: number;
    readonly sex: string;
    eat: () => void;
}
class Infos implements Info {
    name: string;
    age?: number | undefined;
    sex: string;
    eat: () => void;
}
// ● 使用接口拓展，定义接口继承上一题的类接口，并新增（work方法（10分）
interface Infoss extends Infos {
    work: () => void
}
// ● 定义一个符合上诉接口要求的类（10分）
class Infosss implements Infoss {
    work: () => void;
    name: string;
    age?: number | undefined;
    sex: string;
    eat: () => void;
}



// ● 定义一个装饰器（10分）
function Path(target: any) {
    console.log("张凯", target);
}
@Path
class Paths { }
// ● 定义一个装饰器工程（10分）
function PathS(value: string) {
    return function (target: any) {
        console.log("---", value, target);
    }
}
@PathS("张凯")
class Infosy {

}
// ● 定义一个类装饰器（10分）
function Pathq(path: string) {
    return function (target: Function) {
        target.prototype.asd = path
    };
}

@Pathq('张凯')
class Hello {
    asd: any;
    constructor() { }
}

console.log(Hello.prototype.asd);// 输出：{ asd: '张凯' }
let hello = new Hello();
console.log(hello.asd)
// ● 定义一个方法装饰器（10分）
function get(params: any) {
    return function (target: any, methodName: any, desc: any) {
        console.log(params, methodName, desc);
        // 扩展属性
        target.apiUrl = '张三疯';
        // 扩展方法
        target.app = function () {
            console.log('张无忌');
        }

        // 修改装饰器的方法，把装饰器方法里面传入的参数都改为string类型
        // 1保存当前的方法
        let oMethod = desc.value;
        // 2改写方法
        desc.value = function (...arr: any[]) {
            arr = arr.map(e => {
                return String(e);
            })

            // 调用未改写的方法
            oMethod.apply(this, arr);
        }
    }
}

class HttpClient {
    public url: any | undefined;
    constructor() {

    }

    @get('http://www.baidu.com')
    getData(...arr: any[]) {
        console.log('我是getData里面的方法', arr);
    }
}

let http: any = new HttpClient();
console.log(http.apiUrl);
http.getData('张凯', 20);
// ● 定义一个访问器装饰器（10分）
// ● 定义一个组合装饰器（10分）
// ● 定义一个属性装饰器（10分）
function DefaultValue(value: string) {
    return function (target: any, propertyName: string) {
        target[propertyName] = value;
    }
}
class HelloS {
    @DefaultValue("world") greeting!: string;
}

console.log(new HelloS().greeting);// 输出: world
// ● 编写函数uniq(str)，返回去掉str重复项的字符串。例如：str=’defddfrt’

   function unip(str:string){
        let strS:string[]=str.split("")
        let newArr:string[] =[]
   for (let i = 0; i < strS.length; i++) {
          if(newArr.indexOf(strS[i])==-1){
              newArr.push(strS[i])
          }
   }
  return newArr.join("")


   }
    console.log(unip('defddfrt'));


// ● 点击按钮，在div中显示一个随机验证码，随机验证码(长度为4)，且验证码的颜色也是随机的；
// ，随机验证码的字体大小为12-30px的随机大小
// ● 封装一个函数More(arr),arr[1，5，1，8]参数为数组，返回参数中出现次数最多的元素，
// 并打印出现的次数。（选做：定义泛型函数）
function More(arr:number[]) {
    let num=0
     let arr1:any=arr.sort((a,b)=>a-b)
      for (let i = 0; i < arr1.length; i++) {
          if(arr1[i]==arr1[i+1]){
              num=arr[i]
          }
      }

    return num
}
console.log(More([6, 5, 6, 8,8,8,8]));





// ● 装一个封函数unite()，传入两个或两个以上的数组，返回一个以给定的原数组排序的不包含重复值的新数组。
// 说明：所有数组中的左右值都应该以原始顺序被包含在内，但是在最终的数组中不包含重复值；
// 例如：unite([1,3,2],[5,2,1,4],[2,1]) //返回结果：[1,3,2,5,4]；unite([1,2,3],[5,2,1,4],[2,1],[6,7,8]) 
//返回结果:[1,2,3,5,4,6,7,8]

function unite(arr: number[],arr1:number[],arr2:number[]) {
 let newArr:number[] = [...arr,...arr1,...arr2]
      let newArr1:number[] = []
      for (let i = 0; i < newArr.length; i++) {
            if(newArr1.indexOf(newArr[i])==-1){
                newArr1.push(newArr[i])
            }
      }
      return newArr1
}
console.log(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]));






// ● 封装一个findLongestWord(str)函数，str是个英文句子，实现如下功能：找出str句子中最长的单词，并计算它的长度。
// 例如。"The quick brown fox jumped over the lazy dog." 
//  findLongestWord("The quick brown fox jumped over the lazy dog."); //6  
//  findLongestWord("I believe I can do it.");//7
function findLongestWord(str:string) {
    //去除所有的点
   let str1=str.replace(/\./g,"")
    let str2=str1.split(" ")
    let str3=str2.sort((a,b)=>b.length-a.length)
     return str3[0]
}
console.log(findLongestWord("The quick brown fox jumped over the lazy dog."));//6 
console.log(findLongestWord("I believe I can do it."));//7
// ● 封装一个泛型类GetMax;实现找出数组中的最大值，以及最大值下标。
    class GetMax<T>{
        arr:T[]
        constructor(arr:T[]){
           this.arr = arr
        }
      Max(){
          let max =0;
          let ind=0;
        this.arr.forEach((item,index)=>{
            if(typeof item=="number"&&item>max){
                max=item,
                ind=index
            }
        })
        return {
            max,ind
        }
      }
    }
    let getMax=new GetMax<number>([1,5,4,6,3,8,7])
     console.log(getMax.Max());
     
// ● 声明一个类装饰器，给类添加新的属性和方法  Animal。
// ● 声明一个属性装饰器，并作用到类的属性上，在控制台输出